#include <signal.h>
#include <unistd.h>

#include <iostream>
#include <string>

#define BUF_SIZE 200

using namespace std;

// SIGALRM handler: interrupts blocked system call
static void handler(int sig) { cout << "Caught signal " << sig << endl; }

int main(int argc, char* argv[]) {
    if (argc > 1 && string(argv[1]) == "--help") {
        cout << argv[0] << " [num-secs [restart-flag]]" << endl;
        return 0;
    }

    // Set up handler for SIGALRM. Allow system calls to be interrupted,
    // unless second command-line argument was supplied.
    struct sigaction sa;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags   = argc > 2 ? SA_RESTART : 0;
    sa.sa_handler = handler;
    if (sigaction(SIGALRM, &sa, nullptr) == -1) {
        perror("sigaction");
        return 1;
    }

    alarm((argc > 1) ? stoi(argv[1]) : 10);

    char buf[BUF_SIZE];
    buf[BUF_SIZE - 1] = '\0';
    auto numRead      = read(STDIN_FILENO, buf, BUF_SIZE - 1);

    auto savedErrno = errno; // In case alarm() changes it
    alarm(0);                // Ensure timer is turned off
    errno = savedErrno;

    // Determine result of read()
    if (numRead == -1) {
        if (errno == EINTR) {
            cout << "Read timed out" << endl;
        } else {
            perror("read");
            return 1;
        }
    } else {
        cout << "Successful read " << numRead << " bytes: " << buf << endl;
    }

    return 0;
}
